<?
    /* -*- Mode: PHP5; tab-width: 4; indent-tabs-mode: nil; basic-offset: 4 -*- */

    /*********************************************************
    *            --== InArch ==--
    *
    * This is the key class to all the admin side data nodes.
    * It is extended into child classes which do all the work.
    *
    * @author Kulikov Alexey <a.kulikov@gmail.com>
    * @version n/a
    * @since 25.05.2005
    * @copyright essentialmind.com 2005
    *
    *********************************************************/

    /***
    * Abstract Class adminNode
    ****
    * Main purpose of this class is to handle all the template logic
    * any part of any admin node may have. Moreover, this class is
    * responsible for the display of any child classes templates and
    * results. In other words, anything that reaches the browser
    * goes through this class!
    *
    * This is an abstract class, meaning it has to be extended to add
    * the neccessary functionality. Base methods have already been
    * implemented and finalized.
    ****
    * @package adminNodes
    * @author A Kulikov <a.kulikov@gmail.com>
    * @version n/a
    * @since 25.05.2005
    * @copyright essentialmind.com 2005
    ***/
    abstract class adminNode{

        /**
         * reference to the ADODB Connection
         *
         * @var ADOConnection
         */
        protected $db;

        /**
         * reference to the template parser
         *
         * @var mySmarty
         */
        protected $smarty;

        /**
         * reference to the log object
         *
         * @var object
         */
        protected $log;

        /**
         * name of the template
         *
         * @var string
         */
        protected $action;

        /**
         * The requested object
         *
         * @var int
         */
        protected $object;

        /**
         * The page requested, useful in redirects
         *
         * @var string
         */
        protected $request;

        /**
         * The parent node of this object (if any)
         *
         * @var int
         */
        protected $nodeid;

        /**
         * reference to the page id in the pagemap table (if any)
         *
         * @var int
         */
        protected $pageref;

        /**
         * reference to the node id in the object map (if any)
         *
         * @var int
         */
        protected $noderef;

        /* --------------- END VARIABLE DECLARATION ----------------- */

        /**
         * clientNode::__construct()
         *
         * @param object $db     - Reference to the ADODB Connection
         * @param object $smarty - Reference to Smarty
         * @return void
         **/
        function __construct(ADOConnection $db, mySmarty $smarty, $log){
            $this->db       = $db;
            $this->smarty   = $smarty;
            $this->log      = $log;
            $this->pageref  = (int)$_GET['id'];
            $this->noderef  = (int)$_GET['node'];

            if ($_GET['action'] == 'getPageInfo') {
                $this->object   = (int)$this->db->getOne("SELECT pageid FROM pagemap WHERE version = 1 AND id = ".$_REQUEST['id']);
            }

            //path to smarty
            if($_GET['action'] == 'edit'){
                //give path to node to smarty
                $myTree = new tree($this->db,'structure LEFT JOIN objectmap ON (structure.id = objectmap.nodeid)',null,'id, url, level, title');

                //we have to differentiate between folder and pages, pages have precedence!
                if($this->pageref > 0){ //it is a page call                  
                    $this->object   = (int)$this->db->getOne("SELECT pageid FROM pagemap WHERE version = 1 AND id = ".$this->pageref);
                    $this->request  = $GLOBALS['_CONFIG']['admin_root'].$_GET['view'].'/?action=edit&id='.$this->pageref;
                    $this->nodeid   = (int)$this->db->getOne("SELECT nodeid FROM pagemap WHERE version = 1 AND id = ".$this->pageref);

                    //get the full path to the page
                    $path           = $myTree->getPathStack($this->nodeid,true);
                    $properties     = $this->getProperties($path);
                    $datablocks     = $this->getMyDatablocks($path,true);

                    //datablocls
                    $this->smarty->assign('myDatablocks',$datablocks);
                    $this->smarty->assign('datablocks',$this->getDatablocks($datablocks,true));

                    //add page specific records
                    $path[]         = array('title'=>$this->db->getOne("SELECT title FROM pagemap WHERE version = 1 AND id = ".$this->pageref));
                    $properties     = array_merge($properties,$this->db->getAssoc("SELECT name AS key, id, name, value, 1 as local FROM properties AS p, property_page_mapping AS pm WHERE pm.propid = p.id AND pm.pageid = ".$this->pageref));

                    //process files
                    $filePath       = ROOT.'files'.DIRECTORY_SEPARATOR.'pages'.DIRECTORY_SEPARATOR.$this->pageref.DIRECTORY_SEPARATOR;


                    //tags
                    $this->smarty->assign('tags',$this->getTags());
                    $this->smarty->assign('tags_new',$this->getTags(true));

                }else{ // it is a folder call
                    $this->object   = (int)$this->db->getOne("SELECT objectid FROM objectmap WHERE version = 1 AND nodeid = ".$this->noderef);
                    $this->request  = $GLOBALS['_CONFIG']['admin_root'].$_GET['view'].'/?action=edit&node='.$this->noderef;

                    //get the full path to the node
                    $path           = $myTree->getPathStack($this->noderef,true);
                    $properties     = $this->getProperties($path);
                    $datablocks     = $this->getMyDatablocks($path);

                    //process files
                    $filePath       = ROOT.'files'.DIRECTORY_SEPARATOR.'nodes'.DIRECTORY_SEPARATOR.$this->noderef.DIRECTORY_SEPARATOR;

                    //datablocls
                    $this->smarty->assign('myDatablocks',$datablocks);
                    $this->smarty->assign('datablocks',$this->getDatablocks($datablocks));
                }

                $this->smarty->assign('sitePath',$path);
                $this->smarty->assign('properties',$properties);
                $this->smarty->assign('files',$this->getFiles($filePath));
            }

            //mark the client with a cookie of parent's location
            setcookie("probableParent",$this->nodeid,time()+60*60,"/");

            // passing variables into cookies for pdw_file_manager
            setcookie("currentFilePath",$this->getStorePath(),time()+60*60*24*30,"/");
            setcookie("ina_root",INA_ROOT,time()+60*60*24*30,"/");
            setcookie("solution_root",ROOT,time()+60*60*24*30,"/");
        }


        /**
         * Walks the path array and fills it with dynamic properties from the DB
         *
         * @param array $path
         * @return array
         */
        private function getProperties($path){
            $properties = array();
            $myProps    = array();

            //typecast
            $path       = (array)$path;

            //get some numbers
            $total      = count($path);

            //get the properties
            foreach($path as $key => $value){
                if($key == $total-1){
                    $properties = $this->db->getAssoc("SELECT name AS key, id, name, value, 1 as local FROM properties AS p, property_node_mapping AS pm WHERE pm.propid = p.id AND pm.nodeid = $value[id]");

                }else{
                    $properties = $this->db->getAssoc("SELECT name AS key, id, name, value FROM properties AS p, property_node_mapping AS pm WHERE pm.propid = p.id AND pm.nodeid = $value[id]");
                }
                $myProps    = array_merge($myProps,$properties);
            }
            return $myProps;
        }


        /**
         * Enter description here...
         *
         * @param string $path
         * @return array
         */
        private function getFiles($path){
            $files = array();
            $tentry = array();

            if(is_dir($path)){
                $d = dir($path);
                while (false !== ($entry = $d->read())){
                    if(!is_dir($path.$entry)){
                        $files[] = array(
                                            'name'  =>  $entry,
                                            'id'    =>  str_replace('.','_',$entry),
                                            'size'  =>  ceil(filesize($path.$entry)/1024).' Kb'
                                        );
                    }
                }
                $d->close();
            }
            return $files;
        }


        /**
         * Enter description here...
         *
         * @param int $page
         * @return array
         */
        private function getDatablocks($existing,$page=false){

            $all = $this->db->getAssoc("SELECT tag AS key, id, title, tag FROM datablocks WHERE global = TRUE ORDER BY title");
            return array_diff_assoc($all,$existing);
        }


        /**
         * Enter description here...
         *
         * @param int $page
         * @return array
         */
        private function getMyDatablocks($path,$page=false){

            $blocks   = array();
            $myBlocks = array();
            foreach((array)$path as $value){
                //$properties = $this->db->getAssoc("SELECT name AS key, id, name, value FROM properties AS p, property_node_mapping AS pm WHERE pm.propid = p.id AND pm.nodeid = $value[id]");
                $blocks = $this->db->getAssoc("SELECT
                                                    datablocks.tag AS key,
                                                    datablocks.id AS id,
                                                    datablocks.title AS title,
                                                    datablock_node_mapping.nodeid AS node,
                                                    datablocks.tag AS tag
                                                FROM datablock_node_mapping, datablocks
                                                WHERE datablock_node_mapping.inherit = TRUE
                                                AND datablock_node_mapping.blockid = datablocks.id
                                                AND datablock_node_mapping.nodeid = ".$value['id']);

                $myBlocks    = array_merge($myBlocks,$blocks);
            }

            if(!$page){
                return array_merge($myBlocks,$this->db->getAssoc("SELECT
                                                                        datablocks.tag AS key,
                                                                        datablocks.id AS id,
                                                                        datablocks.title AS title,
                                                                        datablock_node_mapping.nodeid AS node,
                                                                        datablocks.tag AS tag,
                                                                        1 AS local
                                                                    FROM datablock_node_mapping, datablocks
                                                                    WHERE datablock_node_mapping.blockid = datablocks.id
                                                                    AND datablock_node_mapping.nodeid = ".$this->noderef));
            }else{
                return array_merge($myBlocks,$this->db->getAssoc("SELECT
                                                                        datablocks.tag AS tag,
                                                                        datablocks.id AS id,
                                                                        datablocks.title AS title,
                                                                        datablock_page_mapping.pageid AS page,
                                                                        datablocks.tag AS tag,
                                                                        1 AS local
                                                                    FROM datablock_page_mapping, datablocks
                                                                    WHERE datablock_page_mapping.blockid = datablocks.id
                                                                    AND pageid = ".$this->pageref));
            }
        }


        /**
         * Manage the upload of a node picture ;)
         *
         */
        protected function uploadPicture($key='nodeimage', $tag=null, $width=null, $height=null){

            if(isset($_FILES[$key]['name']) and !empty($_FILES[$key]['name'])){
                //cast objects
                $uploader   = new fileUploader();

                //prepare file name
                $fileName = 'original'.$tag.'.jpg';
                $filePath = $this->getImagePath();
                
                if($uploader->preparePath($filePath)){
                    $uploader->copyJPEG($_FILES[$key]['tmp_name'],$filePath.$fileName,1600,1280);
                    $uploader->copyJPEG($filePath.$fileName,$filePath.'640x480'.$tag.'.jpg',640,480);
                    $uploader->copyJPEG($filePath.$fileName,$filePath.'320x240'.$tag.'.jpg',320,240);
                    $uploader->copyJPEG($filePath.$fileName,$filePath.'160x120'.$tag.'.jpg',160,120);
                    $uploader->copyJPEG($filePath.$fileName,$filePath.'80x60'.$tag.'.jpg',80,60);

                    if($width && $height){
                        $uploader->copyJPEG($filePath.$fileName,$filePath.$width.'x'.$height.$tag.'.jpg',$width,$height); 
                    }

                    //create squares
                    $uploader->createSquare($filePath.$fileName,$filePath.'200x200'.$tag.'.jpg',200);
                    $uploader->createSquare($filePath.$fileName,$filePath.'150x150'.$tag.'.jpg',150);
                    $uploader->createSquare($filePath.$fileName,$filePath.'125x125'.$tag.'.jpg',125);
                    $uploader->createSquare($filePath.$fileName,$filePath.'100x100'.$tag.'.jpg',100);
                    $uploader->createSquare($filePath.$fileName,$filePath.'60x60'.$tag.'.jpg',60);
                    $uploader->createSquare($filePath.$fileName,$filePath.'40x40'.$tag.'.jpg',40);

                    if($width){
                        $uploader->createSquare($filePath.$fileName,$filePath.$width.'x'.$width.$tag.'.jpg',$width);
                    }

                    //make a note of the ajax request
                    $this->log->recordAction("Uploaded image file! ".$filePath.$fileName);

                    return true;
                }
            }

            return false;
        }


        protected function getImagePath(){
            if(!empty($_GET['node'])){
                $filePath = ROOT.'files'.DIRECTORY_SEPARATOR.'nodes'.DIRECTORY_SEPARATOR.(int)$_GET['node'].DIRECTORY_SEPARATOR.'image'.DIRECTORY_SEPARATOR;
            }else{
                $pageType = $this->db->getOne("SELECT pagetype FROM pagemap WHERE id = ".(int)$_REQUEST['id']);
                $filePath = ROOT.'files'.DIRECTORY_SEPARATOR.'pages'.DIRECTORY_SEPARATOR.$pageType.'__'.$this->object.DIRECTORY_SEPARATOR.'image'.DIRECTORY_SEPARATOR;
            }
            //echo $filePath;exit;
            return $filePath;
        }

        protected function getFilePath(){
            if(!empty($_GET['node'])){
                $filePath = ROOT.'files'.DIRECTORY_SEPARATOR.'nodes'.DIRECTORY_SEPARATOR.(int)$_GET['node'].DIRECTORY_SEPARATOR;
            }else{
                $pageType = $this->db->getOne("SELECT pagetype FROM pagemap WHERE id = ".(int)$_REQUEST['id']);
                $filePath = ROOT.'files'.DIRECTORY_SEPARATOR.'pages'.DIRECTORY_SEPARATOR.$pageType.'__'.$this->object.DIRECTORY_SEPARATOR;
            }
            return $filePath;
        }

        protected function getStorePath(){
            if(!empty($_GET['node'])){
                $filePath = 'files'.DIRECTORY_SEPARATOR.'nodes'.DIRECTORY_SEPARATOR.(int)$_GET['node'].DIRECTORY_SEPARATOR;
            }else{
                $pageType = $this->db->getOne("SELECT pagetype FROM pagemap WHERE id = ".(int)$_REQUEST['id']);
                $filePath = 'files'.DIRECTORY_SEPARATOR.'pages'.DIRECTORY_SEPARATOR.$pageType.'__'.$this->object.DIRECTORY_SEPARATOR;
            }
            return $filePath;
        }

        protected function getTags($inverse=false){
            if($this->pageref > 0){
                if($inverse){
                    $present = $this->db->getCol("SELECT tags.id FROM tag_page_map LEFT JOIN tags ON tag_page_map.tag_id = tags.id WHERE tag_page_map.page_id = ".$this->pageref); $present[] = 0;
                    $present = array_filter($present); $present[] = 0;
                    return $this->db->getAll("SELECT tags.name, tags.id FROM tags WHERE tags.id NOT IN(".implode(',',$present).") ORDER BY tags.name");
                }else{
                    return $this->db->getAll("SELECT tags.name, tags.id FROM tag_page_map LEFT JOIN tags ON tag_page_map.tag_id = tags.id WHERE tag_page_map.page_id = ".$this->pageref." ORDER BY tags.name");
                }
            }
            return array();
        }


        /* -------------- ABSTRACT METHODS -------------------------------------- */

        /**
         * Method signature. Forces the child class to implement
         * this method, which will set the HTML template needed for
         * the child's operation
         *
         * @return
         **/
        abstract protected function setTemplate();


        /**
         * Method Signature. Forces the child class to implement
         * a data processor.
         *
         * @return
         **/
        abstract protected function process();

        /**
         * Method Signature. Forces child class to implement a
         * method which will handle a default add action to the
         * dedicated table
         *
         * @return integer ID of new object
         * @see ajaxAddPage
         * @see ajaxAddNode
         **/
        abstract public function addInstance();

        
        /**
         * Method Signature. Forces child class to implement a
         * method which will return informations for the sidebar
         * in INA
         *
         *
         * @return html code to insert in template
         **/
        public function sidebarInfo() {
            return null;
        }
        
        


        /* -------------- /ABSTRACT METHODS ------------------------------------- */


        /**
         * Does all the dirty work with updating the page title
         * and setting it's state to published
         *
         */
        protected function updatePageStatus(){
            //update title -- very important!
            $myPage = new pageInserter($this->db,$this->log);
            $myPage->updatePage($this->pageref,$_POST['title']);

            //publish page -- will be changes, once WF state processing is active
            //$myPage->publishPage($this->pageref);
        }


        /**
         * Does all the dirty work with updating the folder title
         * and setting it's other states
         *
         * @yukk
         */
        protected function updateNodeStatus(){
            //some bogus check
            if(empty($_POST['title'])){
                $title = 'n/a';
            }else{
                $title = $_POST['title'];
            }

            $this->db->Execute("UPDATE objectmap SET title = '".$title."' WHERE version = 1 AND nodeid = ".$this->noderef);
        }


        /**
         * Sets the name of an action template
         *
         * @param string $action - Name of the action template to be used
         * @return void
         **/
        final function setActionTemplate($action){
            $this->action = $action;
        }


        /**
         * Returs the name of the currently set action template
         *
         * @return string
         **/
        final function getActionTemplate(){
            return $this->action;
        }


        /**
         * Processes the controller and assigns values to smarty
         *
         */
        final function display(){
            $this->setTemplate(); // TODO here is maybe the router for template pathes
            $this->process();
            
            $solution_file =    ROOT . "templates" . DIRECTORY_SEPARATOR .
                                "admin" . DIRECTORY_SEPARATOR . $this->getActionTemplate();
            // var_dump($solution_file)    ;
            $used_template = '';
            if (file_exists($solution_file)) {
                $used_template = $solution_file;
            } else { // we use the admin 
                $used_template = $this->getActionTemplate();
            }


            $this->smarty->assign("subActionTemplate",$used_template);
            $this->smarty->assign('filePath',$this->getStorePath());
            $this->smarty->assign('sidebarInfo',$this->sidebarInfo());
        }
    }
?>